package com.system.core.plugins.mybatis;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.PrecisionModel;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKBWriter;
import org.locationtech.jts.io.WKTReader;

import lombok.SneakyThrows;
import net.postgis.jdbc.PGgeometry;
import net.postgis.jdbc.geometry.binary.BinaryParser;

public class PGgeometryTypeHandler extends BaseTypeHandler<Geometry> {

	private final GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4490); // 默认SRID
	private final WKBReader wkbReader = new WKBReader(geometryFactory);
	private final WKTReader wktReader = new WKTReader(geometryFactory);;
	private final WKBWriter wkbWriter = new WKBWriter(2, true); // 2D with SRID

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType)
			throws SQLException {
		try {
			// 将 JTS Geometry 转换为 WKB 字节数组
			byte[] wkb = wkbWriter.write(parameter);

			// 使用 BinaryParser 解析 WKB 字节数组
			BinaryParser parser = new BinaryParser();
			net.postgis.jdbc.geometry.Geometry geom = parser.parse(wkb);

			// 创建 PGgeometry 对象
			PGgeometry pgGeometry = new PGgeometry(geom);
			ps.setObject(i, pgGeometry);
		} catch (Exception e) {
			throw new SQLException("Error setting Geometry parameter: " + e.getMessage(), e);
		}
	}

	@Override
	public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
		Object obj = rs.getObject(columnName);
		return convertToGeometry(obj);
	}

	@Override
	public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		Object obj = rs.getObject(columnIndex);
		return convertToGeometry(obj);
	}

	@Override
	public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		Object obj = cs.getObject(columnIndex);
		return convertToGeometry(obj);
	}

	@SneakyThrows
	private Geometry convertToGeometry(Object obj) {
		if (obj == null) {
			return null;
		}

		if (obj instanceof PGgeometry) {
			PGgeometry pgGeom = (PGgeometry) obj;
			try {
				// 获取几何对象的字符串表示（可能是 EWKT 格式）
				String geomStr = pgGeom.getGeometry().toString();

				if (geomStr.startsWith("SRID=")) {
					// 提取 SRID 和几何部分
					String[] parts = geomStr.split(";");
					int srid = Integer.parseInt(parts[0].substring(5));
					String wkt = parts[1];

					// 使用 WKTReader 解析
					Geometry geometry = wktReader.read(wkt);
					geometry.setSRID(srid);
					return geometry;
				} else {
					// 直接解析 WKT
					WKTReader reader = new WKTReader(geometryFactory);
					return reader.read(geomStr);
				}
			} catch (Exception e) {
				throw new SQLException("Error parsing geometry: " + e.getMessage(), e);
			}
		}

		if (obj instanceof byte[]) {
			// 直接处理WKB字节数组
			return wkbReader.read((byte[]) obj);
		}

		throw new SQLException("Unsupported geometry type: " + obj.getClass().getName());
	}

}
